package com.ygqh.baby.service.impl;

import java.math.BigDecimal;
import java.util.*;

import com.ygqh.baby.ao.*;
import com.ygqh.baby.constant.Constant;
import com.ygqh.baby.po.*;
import com.ygqh.baby.mapper.YgWholesalerPrebillRecordMapper;
import com.ygqh.baby.service.*;
import com.ygqh.baby.template.AbstractDiffDateTemplate;
import com.ygqh.baby.utils.DateConvertUtils;
import com.ygqh.baby.utils.ExceptionUtil;
import com.ygqh.baby.utils.MailUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.util.Assert;

import java.util.stream.Collectors;

import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @author Ss
 */
@Service
public class YgWholesalerPrebillRecordServiceImpl implements YgWholesalerPrebillRecordService {

	private final Logger logger = LoggerFactory.getLogger(this.getClass());

	@Autowired
	private YgWholesalerPrebillRecordMapper ygWholesalerPrebillRecordMapper;
	@Autowired
	private YgWholesalerService ygWholesalerService;
	@Autowired
	private YgFrameCodeService ygFrameCodeService;
	@Autowired
	private YgWholesalerBillRecordService ygWholesalerBillRecordService;
	@Autowired
	private YgWholesalerPrebillRecordDetailService ygWholesalerPrebillRecordDetailService;
	@Autowired
	private ScheduleJobService scheduleJobService;
	@Autowired
	private YgWholesalerDeliveryOrderDetailService ygWholesalerDeliveryOrderDetailService;
	@Autowired
	private YgWholesalerSkuService ygWholesalerSkuService;
	@Autowired
	private MailUtil mailUtil;

	@Override
	public List<YgWholesalerPrebillRecord> find() {
		YgWholesalerPrebillRecordExample example = new YgWholesalerPrebillRecordExample();
		example.createCriteria().andStatusEqualTo(DataStatus.Valid.name());
		return ygWholesalerPrebillRecordMapper.selectByExample(example);
	}

	@Override
	public int findCount() {
		YgWholesalerPrebillRecordExample example = new YgWholesalerPrebillRecordExample();
		example.createCriteria().andStatusEqualTo(DataStatus.Valid.name());
		return ygWholesalerPrebillRecordMapper.countByExample(example);
	}

	@Override
	public YgWholesalerPrebillRecord findById(Long id) {
		return ygWholesalerPrebillRecordMapper.selectByPrimaryKey(id);
	}


	@Override
	public int save(YgWholesalerPrebillRecord ygWholesalerPrebillRecord) {
		return ygWholesalerPrebillRecordMapper.insertSelective(ygWholesalerPrebillRecord);
	}

	@Override
	public int update(YgWholesalerPrebillRecord ygWholesalerPrebillRecord) {
		return ygWholesalerPrebillRecordMapper.updateByPrimaryKeySelective(ygWholesalerPrebillRecord);
	}

	@Override
	public int deleteSoft(Long[] ids) {
		Assert.notEmpty(ids);
		YgWholesalerPrebillRecordExample example = new YgWholesalerPrebillRecordExample();
		example.createCriteria().andIdIn(Arrays.asList(ids));
		YgWholesalerPrebillRecord record = new YgWholesalerPrebillRecord();
		record.setStatus(DataStatus.Delete);
		return ygWholesalerPrebillRecordMapper.updateByExampleSelective(record, example);
	}

	@Override
	public int deleteSoft(Long id) {
		return this.deleteSoft(new Long[]{id});
	}

	@Override
	public int saveOrUpdate(YgWholesalerPrebillRecord ygWholesalerPrebillRecord) {
		int r;
		if (ygWholesalerPrebillRecord.getId() != null) {
			r = this.update(ygWholesalerPrebillRecord);
		} else {
			r = this.save(ygWholesalerPrebillRecord);
		}
		return r;
	}

	@Override
	public ResultSet<YgWholesalerPrebillRecord> search(QueryInfo queryInfo, String wholesalerName, Date startDate, Date endDate, String billCode, String prebillCode,
													   CommitStatus commitStatus) {
		if (startDate != null) {
			startDate = DateConvertUtils.getDateStart(startDate);
		}
		if (endDate != null) {
			endDate = DateConvertUtils.addDay(DateConvertUtils.getDateStart(endDate), 1);
		}
		int count = ygWholesalerPrebillRecordMapper.countSuper(wholesalerName, startDate, endDate, billCode, prebillCode, commitStatus);
		if (count == 0) {
			return new ResultSet<>();
		}
		List<YgWholesalerPrebillRecord> list = ygWholesalerPrebillRecordMapper.selectSuper(queryInfo, wholesalerName, startDate, endDate, billCode, prebillCode,
				commitStatus);
		return new ResultSet<>(count, list);
	}

	@Override
	public void editPrebillRecord(YgWholesalerPrebillRecord record) {
		this.validateEditParam(record);

		YgWholesaler wholesaler = new YgWholesaler();
		if (record.getId() != null) {
			YgWholesalerPrebillRecord recordFromDB = this.findById(record.getId());
			Assert.notNull(recordFromDB, "预结单不存在");
			wholesaler.setAmountDuePrice(record.getPrebillPrice().subtract(recordFromDB.getPrebillPrice()));

			record.setWholesalerId(null);
			this.update(record);
		} else {
			wholesaler.setAmountDuePrice(record.getPrebillPrice());

			record.setCreateBy(record.getUpdateBy());
			record.setCreateTime(record.getUpdateTime());
			record.setPrebillCode(getCode("Y", record.getUpdateTime()));
			record.setStartDate(record.getCreateTime());
			record.setEndDate(record.getCreateTime());
			this.save(record);
		}

		wholesaler.setId(record.getWholesalerId());
		wholesaler.setUpdateTime(record.getUpdateTime());
		wholesaler.setUpdateBy(record.getUpdateBy());
		ygWholesalerService.updateAmountDuePrice(wholesaler);
	}

	@Override
	public List<YgWholesalerPrebillRecord> findListByWholesalerId(Long wholesalerId, CommitStatus commitStatus) {
		return this.findListByWholesalerId(wholesalerId, null, commitStatus);
	}

	@Override
	public List<YgWholesalerPrebillRecord> findListByWholesalerId(Long wholesalerId, WholeSaleRecordType recordType, CommitStatus commitStatus) {
		Assert.notNull(wholesalerId, "批发商id不能为空");
		return ygWholesalerPrebillRecordMapper.selectListByWholesalerId(wholesalerId, recordType, commitStatus);
	}

	@Override
	public void commitPrebillRecord(List<String> prebillCodeList, String handler) {
		List<YgWholesalerPrebillRecord> prebillRecordList = this.findByPrebillCode(prebillCodeList, CommitStatus.WaitingCommit);
		Assert.notEmpty(prebillRecordList, "待提交的预接单不存在");
		YgWholesalerPrebillRecord prebillRecord = prebillRecordList.get(0);
		BigDecimal amountDuePrice = prebillRecordList.stream().map(YgWholesalerPrebillRecord::getPrebillPrice).reduce(BigDecimal::add).get();
		Date now = new Date();

		YgWholesalerBillRecord billRecord = new YgWholesalerBillRecord();
		billRecord.setWholesalerId(prebillRecord.getWholesalerId());
		billRecord.setWholesalerName(prebillRecord.getWholesalerName());
		billRecord.setBillCode("JS" + ygFrameCodeService.getFrameCode(CodeType.Settlement, now));
		billRecord.setAmountDuePrice(amountDuePrice);
		billRecord.setBillStatus(BillStatus.WaitingBill);
		billRecord.setCreateBy(handler);
		billRecord.setCreateTime(now);
		billRecord.setUpdateBy(handler);
		billRecord.setUpdateTime(now);
		ygWholesalerBillRecordService.save(billRecord);

		List<Long> prebillIdList = prebillRecordList.stream().map(YgWholesalerPrebillRecord::getId).collect(Collectors.toList());
		ygWholesalerPrebillRecordMapper.updateCommitStatusByPrebillCode(prebillIdList, billRecord.getBillCode(), now, handler);
	}

	@Override
	public List<YgWholesalerPrebillRecord> findByPrebillCode(List<String> prebillCodeList, CommitStatus commitStatus) {
		Assert.notEmpty(prebillCodeList, "预结单号不能为空");
		return ygWholesalerPrebillRecordMapper.selectByPrebillCode(prebillCodeList, commitStatus);
	}

	@Override
	public void saveReturnOrder(Long wholesalerId, List<YgWholesalerPrebillRecordDetail> prebillRecordDetailList, String handler) {
		Assert.notNull(wholesalerId, "批发商id不能为空");
		this.validateParamForSaveReturn(prebillRecordDetailList);
		YgWholesaler wholesaler = ygWholesalerService.findById(wholesalerId);
		savePrebillRecord(wholesaler, prebillRecordDetailList, handler, WholeSaleRecordType.ReturnOrder, null, null);
	}

	@Override
	public void executeWholesalerPrebillJob(Long wholesalerId) {
		YgWholesaler wholesaler = ygWholesalerService.findById(wholesalerId);
		Assert.notNull(wholesaler, "批发商不存在");
		YgQuartzJob jobMode = YgQuartzJob.Wholesaler;
		String jobName = jobMode.getJobName(wholesalerId.toString());
		ScheduleJob job = scheduleJobService.findJobByJobNames(jobName).get(0);
		Date cronDate = job.getCronDate();
		Date now = new Date();
		if (cronDate.after(now)) {
			// 计划任务的执行时间在当前时间以后，计划任务不作修改
			return;
		}
		cronDate = executePrebillOrderRecord(wholesaler, DateConvertUtils.getDateStart(now));
		if (wholesaler.getBillingCycle() < Constant.STANDARD_DAYS_OF_MONTH) {
			// 按天
			cronDate = DateConvertUtils.addDay(cronDate, wholesaler.getBillingCycle());
		} else {
			cronDate = DateConvertUtils.addMonth(cronDate, 1);
		}
		// 准点延时两小时执行
		cronDate = DateConvertUtils.addMinute(cronDate, 120);
		job.setCron(DateConvertUtils.format(cronDate, DateConvertUtils.DATE_FORMAT_CRON));
		job.setCronDate(cronDate);
		Message message = scheduleJobService.updateJobToSchedule(job);
		if (Message.isSuccess(message)) {
			job.setUpdateBy("task");
			job.setUpdateTime(now);
			scheduleJobService.update(job);
		}
	}

	@Override
	public void updateByDismissedRecord(YgWholesalerPrebillRecord record) {
		ygWholesalerPrebillRecordMapper.updateByDismissedRecord(record);
	}

	@Override
	public void addPrebillOrderRecordPastTime(YgWholesaler wholesaler) {
		Date today = DateConvertUtils.getDateStart(new Date());
		if (wholesaler.getCreateTime().after(today)) {
			// 新建批发商不做处理
			return;
		}
		try {
			executePrebillOrderRecord(wholesaler, today);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			mailUtil.simpleSend("sunshuo@yiigoo.com", "批发商编辑处理出库单异常", ExceptionUtil.getExceptionMsg(e));
		}
	}

	/**
	 * 执行订单结算
	 *
	 * @param wholesaler  批发商
	 * @param executeTime 执行时间
	 * @return 返回最后一次执行时间
	 */
	private Date executePrebillOrderRecord(YgWholesaler wholesaler, Date executeTime) {
		Date startDate;
		List<YgWholesalerPrebillRecord> prebillRecordList = this.findListByWholesalerId(wholesaler.getId(), WholeSaleRecordType.Order, null);
		if (CollectionUtils.isEmpty(prebillRecordList)) {
			startDate = DateConvertUtils.getDateStart(wholesaler.getCreateTime());
		} else {
			startDate = DateConvertUtils.addDay(prebillRecordList.get(0).getEndDate(), 1);
		}
		return new AbstractDiffDateTemplate<YgWholesaler>(wholesaler, wholesaler.getBillingCycle(), startDate, executeTime) {
			@Override
			public void execute(Date startDate, Date endDate) {
				addPrebillOrderRecord(wholesaler, startDate, endDate);
			}
		}.process();
	}

	/**
	 * 保存指定时间段的出库单
	 *
	 * @param wholesaler 批发商
	 * @param startDate  出库开始时间
	 * @param endDate    出库结束时间
	 */
	private void addPrebillOrderRecord(YgWholesaler wholesaler, Date startDate, Date endDate) {
		List<YgWholesalerDeliveryOrderDetail> deliveryOrderDetailList = ygWholesalerDeliveryOrderDetailService.findByShopNo(wholesaler.getShopNo(), startDate, endDate);
		if (CollectionUtils.isEmpty(deliveryOrderDetailList)) {
			return;
		}
		List<YgWholesalerPrebillRecordDetail> detailList = new ArrayList<>(deliveryOrderDetailList.size());
		deliveryOrderDetailList.forEach(d -> {
			YgWholesalerPrebillRecordDetail detail = new YgWholesalerPrebillRecordDetail();
			BeanUtils.copyProperties(d, detail);
			detail.setRecordType(WholeSaleRecordType.Order);
			detailList.add(detail);
		});
		setWholesalerPrice(detailList, wholesaler.getId());
		savePrebillRecord(wholesaler, detailList, "定时结算任务", WholeSaleRecordType.Order, startDate, DateConvertUtils.addDay(endDate, -1));
	}

	/**
	 * 保存预接单
	 *
	 * @param wholesaler              批发商
	 * @param prebillRecordDetailList 预结单明细
	 * @param handler                 操作人
	 */
	private void savePrebillRecord(YgWholesaler wholesaler, List<YgWholesalerPrebillRecordDetail> prebillRecordDetailList, String handler, WholeSaleRecordType recordType,
								   Date startDate, Date endDate) {
		YgWholesalerPrebillRecord record = new YgWholesalerPrebillRecord();
		Date now = new Date();
		if (startDate == null) {
			startDate = now;
		}
		if (endDate == null) {
			endDate = now;
		}
		record.setPrebillCode(getCode("Y", now));
		record.setWholesalerId(wholesaler.getId());
		record.setWholesalerName(wholesaler.getWholesalerName());
		record.setRecordType(recordType);
		record.setStartDate(startDate);
		record.setEndDate(endDate);
		record.setCommitStatus(CommitStatus.WaitingCommit);
		record.setCreateTime(now);
		record.setCreateBy(handler);
		record.setUpdateTime(now);
		record.setUpdateBy(handler);

		// 主单金额
		BigDecimal prebillPrice = BigDecimal.ZERO;
		for (YgWholesalerPrebillRecordDetail detail : prebillRecordDetailList) {
			detail.setRecordType(recordType);
			detail.setPrebillCode(record.getPrebillCode());
			detail.setWholesalerId(wholesaler.getId());
			detail.setWholesalerName(wholesaler.getWholesalerName());
			detail.setCreateBy(handler);
			detail.setCreateTime(now);

			prebillPrice = prebillPrice.add(detail.getWholesalePrice().multiply(BigDecimal.valueOf(detail.getQuantity())));
		}
		if (WholeSaleRecordType.ReturnOrder.equals(record.getRecordType())) {
			prebillPrice = BigDecimal.ZERO.subtract(prebillPrice);
		}
		record.setPrebillPrice(prebillPrice);

		YgWholesaler wholesalerForUpdate = new YgWholesaler();
		wholesalerForUpdate.setId(wholesaler.getId());
		wholesalerForUpdate.setAmountDuePrice(prebillPrice);
		wholesalerForUpdate.setUpdateBy(handler);
		wholesalerForUpdate.setUpdateTime(now);

		this.save(record);
		ygWholesalerPrebillRecordDetailService.saveBatch(prebillRecordDetailList);
		ygWholesalerService.updateAmountDuePrice(wholesalerForUpdate);
	}

	/**
	 * 设置明细批发价
	 *
	 * @param prebillRecordDetailList
	 * @param wholesalerId
	 */
	private void setWholesalerPrice(List<YgWholesalerPrebillRecordDetail> prebillRecordDetailList, Long wholesalerId) {
		List<String> skuCodeList = prebillRecordDetailList.stream().map(YgWholesalerPrebillRecordDetail::getSkuCode).collect(Collectors.toList());
		List<YgWholesalerSku> wholesalerSkuList = ygWholesalerSkuService.findBySkuCode(skuCodeList, wholesalerId);
		Assert.notEmpty(wholesalerSkuList, "批发价未维护，skuCodeList=" + skuCodeList.toString());
		Map<String, List<YgWholesalerSku>> collect = wholesalerSkuList.stream().collect(Collectors.groupingBy(YgWholesalerSku::getSkuCode));
		skuCodeList.removeAll(collect.keySet());
		Assert.isTrue(CollectionUtils.isEmpty(skuCodeList), "批发价未维护，skuCodeList=" + skuCodeList.toString());
		prebillRecordDetailList.forEach(detail -> detail.setWholesalePrice(collect.get(detail.getSkuCode()).get(0).getWholesalePrice()));
	}

	/**
	 * 生成编码
	 *
	 * @param prefix 前缀
	 * @param date   日期
	 * @return
	 */
	private String getCode(String prefix, Date date) {
		return prefix + ygFrameCodeService.getFrameCode(CodeType.Settlement, date);
	}

	/**
	 * 校验退货单参数
	 *
	 * @param prebillRecordDetailList 明细信息
	 */
	private void validateParamForSaveReturn(List<YgWholesalerPrebillRecordDetail> prebillRecordDetailList) {
		Assert.notEmpty(prebillRecordDetailList, "退货单明细不能为空");
		String detailCode = getCode("T", new Date());
		for (YgWholesalerPrebillRecordDetail detail : prebillRecordDetailList) {
			String skuCode = detail.getSkuCode();
			Assert.isTrue(StringUtils.isNotBlank(skuCode), "SKU编码不能为空");
			Assert.notNull(detail.getQuantity(), "SKU数量不能为空，skuCode=" + skuCode);
			Assert.notNull(detail.getWholesalePrice(), "SKU批发价不能为空，skuCode=" + skuCode);
			detail.setDetailCode(detailCode);
		}
	}

	/**
	 * 校验预结单直接编辑的参数
	 *
	 * @param record 预结单
	 */
	private void validateEditParam(YgWholesalerPrebillRecord record) {
		Assert.notNull(record.getRecordType(), "预结单类型不能为空");
		Assert.notNull(record.getPrebillPrice(), "预结金额不能为空");
		switch (record.getRecordType()) {
			case Order:
			case ReturnOrder:
				throw new IllegalArgumentException("订单类型和退单类型不支持直接编辑");
			case Postage:
				Assert.isTrue(record.getPrebillPrice().compareTo(BigDecimal.ZERO) > 0, "运费类型的预结金额不能为负数");
				break;
			case Other:
				break;
			default:
				break;
		}
		if (record.getId() == null) {
			Assert.notNull(record.getWholesalerId(), "批发商id不能为空");
			YgWholesaler wholesaler = ygWholesalerService.findById(record.getWholesalerId());
			Assert.notNull(wholesaler, "批发商不存在");
			record.setWholesalerName(wholesaler.getWholesalerName());
		}
	}

}

